package com.ruoyi.system.service.department.impl;

import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.award.competition.CompetitionAwardInfo;
import com.ruoyi.system.domain.award.research.ResearchAwardInfo;
import com.ruoyi.system.domain.award.teach.TeachAwardInfo;
import com.ruoyi.system.domain.department.Statistics.AwardQueryParam;
import com.ruoyi.system.domain.department.Statistics.AwardReportDTO;
import com.ruoyi.system.domain.honor.person.PersonalHonor;
import com.ruoyi.system.domain.project.book.Book;
import com.ruoyi.system.domain.project.paper.PaperInfo;
import com.ruoyi.system.domain.project.patent.Patent;
import com.ruoyi.system.domain.teacher.Statistics.TeacherStatisticsDTO;
import com.ruoyi.system.domain.teacher.Statistics.TeacherStatisticsRequestVO;
import com.ruoyi.system.mapper.award.competition.CompetitionAwardInfoMapper;
import com.ruoyi.system.mapper.award.party.PartyAwardInfoMapper;
import com.ruoyi.system.mapper.award.research.ResearchAwardInfoMapper;
import com.ruoyi.system.mapper.award.teach.TeachAwardInfoMapper;
import com.ruoyi.system.mapper.honor.PersonalHonorMapper;
import com.ruoyi.system.mapper.honor.TeamHonorMapper;
import com.ruoyi.system.mapper.project.BookMapper;
import com.ruoyi.system.mapper.project.PaperInfoMapper;
import com.ruoyi.system.mapper.project.PatentMapper;
import com.ruoyi.system.service.department.IDepartmentStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * @Description:
 * @Author: LiDeLian
 * @Date: 2023/5/5 0005
 * @Version: 1.0
 */
@Service
public class IDepartmentStaticticsServiceImpl implements IDepartmentStatisticsService {
    @Autowired
    private ResearchAwardInfoMapper researchAwardInfoMapper;//科研获奖信息
    @Autowired
    private TeachAwardInfoMapper teachAwardInfoMapper;//教学获奖信息
    @Autowired
    private PersonalHonorMapper personalHonorMapper;//个人荣誉信息
    @Autowired
    private TeamHonorMapper teamHonorMapper;//团队荣誉信息
    @Autowired
    private BookMapper bookMapper;//书籍信息
    @Autowired
    private PaperInfoMapper paperInfoMapper;//论文信息
    @Autowired
    private PatentMapper patentMapper;//专利信息
    @Autowired
    private PartyAwardInfoMapper partyAwardInfoMapper;//党建获奖信息
    @Autowired
    private CompetitionAwardInfoMapper competitionAwardInfoMapper;

    /**
     * 获取院系各项信息
     *
     * @return
     */
    @Override
   // @Cacheable(value = "departmentStatistics_getIndexInfo", key = "#requestVO.deptId + '-' + #requestVO.year", unless = "#result == null")
    public TeacherStatisticsDTO getIndexInfo(TeacherStatisticsRequestVO requestVO) {
        // 1. 从请求参数中获取用户ID和年份、部门ID
        String userId = requestVO.getUserId();
        String year = requestVO.getYear();
        String deptId = requestVO.getDeptId();

        int researchAwardCount =0;//科研获奖信息
        int personalHonorCount =0;//个人荣誉信息
        int bookCount = 0;//书籍信息
        int paperCount = 0;//论文信息
        // int partyCount = partyAwardInfoMapper.countByDeptIdAndYear(deptId, year);//党建获奖信息
        int teamCount = 0;//团队荣誉信息
        int competitionCount = 0;
        // 2. 调用各mapper查询对应数据（假设各mapper已实现按用户ID和年份统计的方法）
        if(year!=null&&year.equals("2020之前")){
              researchAwardCount = researchAwardInfoMapper.countByDeptIdAndYearBefore(deptId );//科研获奖信息
              personalHonorCount = personalHonorMapper.countByDeptIdAndYearBefore(deptId );//个人荣誉信息
              bookCount = bookMapper.countByDeptIdAndYearBefore(deptId );//书籍信息
              paperCount = paperInfoMapper.countByDeptIdAndYearBefore(deptId );//论文信息
            // int partyCount = partyAwardInfoMapper.countByDeptIdAndYear(deptId );//党建获奖信息
              teamCount = teachAwardInfoMapper.countByDeptIdAndYearBefore(deptId );//团队荣誉信息
              competitionCount = competitionAwardInfoMapper.countByDeptIdAndYearBefore(deptId );
        }else{
              researchAwardCount = researchAwardInfoMapper.countByDeptIdAndYear(deptId, year);//科研获奖信息
              personalHonorCount = personalHonorMapper.countByDeptIdAndYear(deptId, year);//个人荣誉信息
              bookCount = bookMapper.countByDeptIdAndYear(deptId, year);//书籍信息
              paperCount = paperInfoMapper.countByDeptIdAndYear(deptId, year);//论文信息
            // int partyCount = partyAwardInfoMapper.countByDeptIdAndYear(deptId, year);//党建获奖信息
              teamCount = teachAwardInfoMapper.countByDeptIdAndYear(deptId, year);//团队荣誉信息
              competitionCount = competitionAwardInfoMapper.countByDeptIdAndYear(deptId, year);
        }


        // 3. 组装统计结果DTO
        TeacherStatisticsDTO statisticsDTO = new TeacherStatisticsDTO();
        statisticsDTO.setUserId(userId);
        statisticsDTO.setDeptId(deptId);
        statisticsDTO.setResearchAwardCount(researchAwardCount);
        statisticsDTO.setTeachAwardCount(teamCount);
        statisticsDTO.setPersonalHonorCount(personalHonorCount);
        statisticsDTO.setBookCount(bookCount);
        statisticsDTO.setPaperCount(paperCount);
        statisticsDTO.setCompetitionCount(competitionCount);
        //statisticsDTO.setParty(partyCount);
        statisticsDTO.setPatentCount(0);

        return statisticsDTO;
    }
    /**
     * 获奖报表
     * @param param
     * @return
     */
    @Override
    public List<AwardReportDTO> generateReport(AwardQueryParam param) {
        Long deptId = SecurityUtils.getDeptId();
        List<PersonalHonor> teachingAwards = personalHonorMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//个人荣誉信息
        List<ResearchAwardInfo> researchAwards = researchAwardInfoMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//科研获奖信息
        List<TeachAwardInfo> teachAwards = teachAwardInfoMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//教学获奖信息
        List<Book> books = bookMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//书籍信息
        List<PaperInfo> papers = paperInfoMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//论文信息
        List<CompetitionAwardInfo> competitions = competitionAwardInfoMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//竞赛获奖信息
        List<Patent> patents = null;//专利信息

        int partyCount = partyAwardInfoMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//党建获奖信息
        int teamCount = teamHonorMapper.selectByCondition(param.getStartDate(), param.getEndDate(),deptId);//团队荣誉信息

        System.out.println(teachingAwards);

        // 调用聚合方法
        return aggregateData(teachingAwards, teachAwards,researchAwards,papers, books,competitions,patents, partyCount, teamCount);
    }


    /**
     * 数据聚合逻辑：将各类奖项数据合并到AwardReportDTO列表中
     *
     * @param teachingAwards 教学奖项列表
     * @param researchAwards 科研奖项列表
     * @param partyCount
     * @param teamCount
     * @return 聚合后的报表数据列表
     */
    private List<AwardReportDTO> aggregateData(List<PersonalHonor> teachingAwards,
                                               List<TeachAwardInfo> teachAwards,
                                               List<ResearchAwardInfo> researchAwards,
                                               List<PaperInfo> papers,
                                               List<Book> books, List<CompetitionAwardInfo> competitions,
                                               List<Patent> patents,
                                               int partyCount, int teamCount) {
        // 初始化Map时估算容量，减少扩容
        Map<Long, AwardReportDTO> reportMap = new HashMap<>(Math.max(
                teachingAwards.size() +teachAwards.size()+ researchAwards.size() +papers.size()+ books.size()+competitions.size(), 16));

        // 处理个人荣誉数据
        processAwardList(teachingAwards,
                PersonalHonor::getWinnerId,
                PersonalHonor::getWinner,
                this::updatePersonHonorCount,
                reportMap);

        // 处理教学奖项数据
        processAwardList(teachAwards,
                TeachAwardInfo::getTeacherId,
                TeachAwardInfo::getTeacherName,
                this::updateTeachsCount,
                reportMap);
        // 处理论文数据
        processAwardList(papers,
                PaperInfo::getAuthorId,
                PaperInfo::getAuthorName,
                this::updatePapersCount,
                reportMap);

        // 处理科研奖项数据
        processAwardList(researchAwards,
                ResearchAwardInfo::getUserId,
                ResearchAwardInfo::getUserName,
                this::updateResearchAwardCount,
                reportMap);

        // 处理书籍数据
        processAwardList(books,
                Book::getAuthorId,
                Book::getMainAuthorsTranslators,
                this::updateBookCount,
                reportMap);
        //处理比赛数据
        processAwardList(competitions,
                CompetitionAwardInfo::getTeacherId,
                CompetitionAwardInfo::getTeacherName,
                this::updateCompetitionAwardCount,
                reportMap);
        //处理专利数据
        processAwardList(patents,
                patent -> {
                    String teacherIdStr = patent.getTeacherId();
                    // 尝试将字符串转换为Long，转换失败时返回null（会被processAwardList跳过）
                    try {
                        return teacherIdStr != null ? Long.parseLong(teacherIdStr) : null;
                    } catch (NumberFormatException e) {
                        // 可根据需要记录日志，此处简单返回null
                        return null;
                    }
                },
                Patent::getTeacherName,
                this::updatePatentCount,
                reportMap);

        // 计算每个用户的奖项总数，使用安全的null处理
        reportMap.values().forEach(dto -> {
            int total = getSafeInt(dto.getPersonHonor()) +
                 getSafeInt(dto.getResearchAward()) + getSafeInt(dto.getPaper()) + getSafeInt(dto.getTeachingAward())+ getSafeInt(dto.getCompetitionAward())+
                   getSafeInt(dto.getPatent())+ getSafeInt(dto.getBook())+teamCount+partyCount;
            dto.setTotal(total);
            dto.setTeamHonor(teamCount);
            dto.setPartyAward(partyCount);
        });

        return new ArrayList<>(reportMap.values());
    }



    /**
     * 通用奖项列表处理方法
     */
    private <T> void processAwardList(List<T> awardList,
                                      Function<T, Long> userIdExtractor,
                                      Function<T, String> userNameExtractor,
                                      BiConsumer<AwardReportDTO, T> countUpdater,
                                      Map<Long, AwardReportDTO> reportMap) {
        if (CollectionUtils.isEmpty(awardList)) {
            return;
        }

        for (T award : awardList) {
            Long userId = userIdExtractor.apply(award);
            if (userId == null) {
                continue; // 跳过无用户ID的记录
            }

            // 获取或创建DTO，确保新创建的DTO所有计数字段初始化为0
            AwardReportDTO dto = reportMap.computeIfAbsent(userId, k -> createDefaultAwardReportDTO());

            // 首次设置用户信息
            if (dto.getUserId() == null) {
                dto.setUserId(userId);
                dto.setName(userNameExtractor.apply(award));
            }

            // 更新对应类型的计数
            countUpdater.accept(dto, award);
            reportMap.put(userId, dto);
        }
    }

    /**
     * 创建默认的AwardReportDTO，确保所有计数字段初始化为0
     */
    private AwardReportDTO createDefaultAwardReportDTO() {
        AwardReportDTO dto = new AwardReportDTO();
        dto.setPersonHonor(0);
        dto.setResearchAward(0);
        dto.setPaper(0);
        dto.setTeachingAward(0);
        dto.setBook(0);
        dto.setTotal(0);
        dto.setCompetitionAward(0);
        dto.setPatent(0);
        return dto;
    }

    /**
     * 安全获取Integer值，避免null
     */
    private int getSafeInt(Integer value) {
        return value != null ? value : 0;
    }

    /**
     * 更新个人荣誉计数（单独提取方法，提高可读性）
     */
    private void updatePersonHonorCount(AwardReportDTO dto, Object award) {
        dto.setPersonHonor(getSafeInt(dto.getPersonHonor()) + 1);
    }
    /**
     * 获取教学奖项计数
     */
    private void updateTeachsCount(AwardReportDTO awardReportDTO, Object teachAwardInfo) {
        awardReportDTO.setTeachingAward(getSafeInt(awardReportDTO.getTeachingAward()) + 1);
    }

    /**
     * 获取论文计数
     */
    private void updatePapersCount(AwardReportDTO awardReportDTO, Object paperInfo) {
        awardReportDTO.setPaper(getSafeInt(awardReportDTO.getPaper()) + 1);
    }
    /**
     * 更新科研奖项计数
     */
    private void updateResearchAwardCount(AwardReportDTO dto, Object award) {
        dto.setResearchAward(getSafeInt(dto.getResearchAward()) + 1);
    }

    /**
     * 更新书籍计数
     */
    private void updateBookCount(AwardReportDTO dto, Object award) {
        dto.setBook(getSafeInt(dto.getBook()) + 1);
    }
    /**
     * 获取比赛奖项计数
     */
    private void updateCompetitionAwardCount(AwardReportDTO dto, Object competitionAwardInfo) {
        dto.setCompetitionAward(getSafeInt(dto.getCompetitionAward()) + 1);
    }
    /**
     * 获取专利计数
     */
    private void updatePatentCount(AwardReportDTO dto, Object patent) {
        dto.setPatent(getSafeInt(dto.getPatent()) + 1);
    }


}
